package com.fingard.dsp.bank.directbank.alipay01;

import com.alipay.api.CertAlipayRequest;
import com.cfca.util.pki.encoders.UrlBase64;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.SendBankRespose;
import com.fingard.net.WebRequest;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.ParseException;
import java.util.*;

public class ALIPAY01Base extends DirectBase  {
	protected String getCharset() {
		return getBankConfig().getCharset("UTF-8");
	}

	/**
	 *  下载对账单到本地并读取压缩包中业务明细文件内容
	 */
	protected SendBankRespose smsGet(String p_url,String filePath) {
		SendBankRespose retResp = new SendBankRespose();

		URL url = null;
		HttpURLConnection httpUrlConnection = null;
		InputStream fis = null;
		FileOutputStream fos = null;
        Scanner scanner = null;

		try {

			String fileCharset = getBankConfig().getCharset("gbk", "statementFile");

			url = new URL(p_url);
			httpUrlConnection = (HttpURLConnection) url.openConnection();
			httpUrlConnection.setConnectTimeout(50 * 1000);
			httpUrlConnection.setDoInput(true);
			httpUrlConnection.setDoOutput(true);
			httpUrlConnection.setUseCaches(false);
			httpUrlConnection.setRequestMethod("GET");
			httpUrlConnection.setRequestProperty("Charset", "UTF-8");
			httpUrlConnection.connect();
			fis = httpUrlConnection.getInputStream();
			byte[] temp = new byte[1024];
			int b;
			fos = new FileOutputStream(new File(filePath));
			while ((b = fis.read(temp)) != -1) {
				fos.write(temp, 0, b);
				fos.flush();
			}

			StringBuilder content = new StringBuilder();
			ZipFile zip = new ZipFile(filePath, fileCharset);
			@SuppressWarnings("unchecked")
			Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zip.getEntries();

			ZipEntry ze;
			while (entries.hasMoreElements()) {
				ze = entries.nextElement();
				WriteBankLogLn("账单解压后文件列表:" + ze.getName());
				if (ze.getName().contains("TRADE_DETAILS")|| ze.getName().contains("_账务明细.csv")) {
                    scanner = new Scanner(zip.getInputStream(ze), fileCharset);
					while (scanner.hasNextLine()) {
						content.append(scanner.nextLine()+"\n");
					}
				}
			}
			zip.close();

			retResp.retMessage =  content.toString();
		} catch (IOException e) {
			retResp.connState = FailCode.E9999;
			retResp.retMessage = e.getMessage();
			retResp.appendLog(e);
			return retResp;
		} finally {
			try {
				if(fos!=null) fos.close();
				if(fis!=null) fis.close();
				if(scanner!=null) scanner.close();
				if(httpUrlConnection!=null) httpUrlConnection.disconnect();
			} catch (IOException e) {
				this.WriteBankLogLn(e);
			}
		}

		return retResp;
	}



	/**
	 * AliPayClient构造参数，适用于公钥证书模式
	 *
	 * @param actItem
	 * @return
	 */
	protected CertAlipayRequest getCertAlipayRequest(ActSetItem actItem) {
		CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
		certAlipayRequest.setServerUrl(bankFront.serverURL);
		certAlipayRequest.setAppId(actItem.appId);
		certAlipayRequest.setPrivateKey(actItem.ownKeyStorePath);                   //商户私钥
		certAlipayRequest.setFormat("json");
		certAlipayRequest.setCharset(getBankConfig().getCharset("utf-8"));
		certAlipayRequest.setSignType(actItem.signType);
		certAlipayRequest.setCertPath(actItem.oppCertFilePath);                     //开发者应用公钥证书路径
		certAlipayRequest.setAlipayPublicCertPath(actItem.alipayPublicCertPath);    //支付宝公钥证书文件路径
		certAlipayRequest.setRootCertPath(actItem.rootCertPath);                    //支付宝CA根证书文件路径
		return certAlipayRequest;
	}

	/**
	 * 返回HTTP字符串转MAP
	 *
	 * @param srcStr
	 * @return
	 */
	public static Map<String,String> convertToMap(String srcStr) {
		Map<String,String> params = new HashMap<String,String>();

		String[] nodes = srcStr.split("&");
		for (String node : nodes) {
			int index = node.indexOf("=");

			String key = node.substring(0, index);
			String value = node.substring(index+1);

			params.put(key, value);
		}

		return params;
	}

	/**
	 * 创建日志目录
	 */
	protected void logIsExist(){
		File logFile=new File("D:\\Workspaces\\logs\\EposClient");

		if(!logFile.exists()){
			logFile.mkdirs();
		}
	}

	/**
	 * 获取有效时间 (分钟)
	 *
	 * @return 有效时间
	 * @throws ParseException
	 *             日期格式转换异常
	 */
	public String getValidTime(String validTime) throws ParseException {
		if (Long.parseLong(validTime) >= 15*24*60) {
			validTime = "15d";
		} else {
			validTime += "m";
		}
		return validTime;
	}

    /**
     * 将MAP转换为post请求串
     *
     * @return
     */
    public String convertMapToStr(Map<String, String> params) {
        Map<String, String> result = new HashMap<String, String>();
        for (String key : params.keySet()) {
            String value = params.get(key);
            if (value == null || value.equals("") || key.equalsIgnoreCase("sign") || key.equalsIgnoreCase("sign_type")) {
                continue;
            }
            result.put(key, value);
        }

		List<String> keys = new ArrayList<String>(result.keySet());
		Collections.sort(keys);
		String prestr = "";

        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = result.get(key);

            if (i == keys.size() - 1) {//拼接时，不包括最后一个&字符
                prestr = prestr + key + "=" + value;
            } else {
                prestr = prestr + key + "=" + value + "&";
            }
        }
		return prestr;
    }

    /**
     * 将MAP转换为post请求串
     *
     * @return
     */
    public String convertMapToStr1(Map<String, String> params) {
		String reqStr = "";
		for (String key : params.keySet()) {
			if (!key.equals("")) {
				if (reqStr.length() > 0) {
					reqStr += "&";
				}
				reqStr += key + "=" + params.get(key);
			}
		}
		return reqStr;
    }

	/**
	 * 签名
	 */
	public String md5(String tmpStr, ActSetItem actItem) {
		String sign = "";
		try {
			String key = actItem.saltKey;
			tmpStr = tmpStr + key;
			WriteBankLogLn("待签名字段：" + tmpStr);
			sign = DigestUtils.md5Hex(tmpStr.getBytes(getCharset()));
		} catch (Exception e) {
			WriteBankLogLn("签名失败", e);
		}
		return sign;
	}


	/**
     * 签名
     */
    public String getSign(String tmpStr, ActSetItem actItem) {
        String sign = "";
        try {
            WriteBankLogLn("待签名字段：" + tmpStr);
            PrivateKey privateKey = getPrivateKey(actItem.ownKeyStorePath);
            Signature signature = Signature.getInstance("SHA1WithRSA");
            signature.initSign(privateKey);
            signature.update(tmpStr.getBytes(getCharset()));
            byte[] signed = signature.sign();
            sign = new String(UrlBase64.encode(signed), getCharset());
        } catch (Exception e) {
            WriteBankLogLn("签名失败", e);
        }
        return sign;
    }

    private static PrivateKey getPrivateKey(String key) {
        try {
            byte[] keyBytes = Base64.decodeBase64(key.getBytes("UTF-8"));
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            return privateKey;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public String[] sendToBank(String reqStr, String httpUrl) throws Exception {
		String[] retStr = new String[]{"", ""};
		WriteBankLogLn("1.提交银行的地址：" + httpUrl);
		WriteBankLogStep2(reqStr);
		//发送给银行前置机
		WebRequest tmpWebRequest = new WebRequest(httpUrl);
		tmpWebRequest.setConnectTimeout(60000);
		byte[] tmpUpBytes = reqStr.getBytes(getCharset());
		retStr = tmpWebRequest.upload(tmpUpBytes, getCharset());//发送报文+MAC校验码
		WriteBankLogStep3(retStr[1]);

		return retStr;
    }


}
